<style >
.box-header{
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0px 2px 0.5px lightgray;
}
.tool{
  display: flex;
  justify-content: start;
  align-items: center;
}
body{
  padding: 0px;
}
.box-aside{
  padding:30px 10px;
  display:flex;
  flex-direction:column;
  align-items:center;
  position: absolute;
  left:-15%;
  transition:all 3s;
}
.aside-active{
  box-shadow:2px 2px 0.5px lightgray;
  left:0%
}
.box-aside .title{
  display:flex;
  justify-content:center;
  align-items:center;
}
.box-aside .data{
  margin-top:12px;
  font-size:24px;
}
.main-node {
  position:absolute;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
  border-radius: 50%;
  box-shadow: 0 0 5px lightgray;
  font-size: 22px;
  background-color: lightblue
}
.canvas-container{
  width:75%;
  height: 700px;
  transition: all 1s;
}
.tool{
  display: flex;

}
</style>

<template>
  <el-container>
      <el-header class="box-header">
        <div class="operation">
          <el-button  :icon="Plus" :disabled="loading" @click="showDialog" type="primary">添加</el-button>
          <el-button  :icon="Coin" :disabled="loading" @click="exampleVisable=true" type="warning">保存</el-button>
          <el-button  :icon="Delete" :disabled="loading" @click="clearNodes" type="danger">清空</el-button>
        </div>
        <div class="tool">
          <el-tooltip content="日志" placement="top">
            <el-button @click="showLog" type="primary" title="日志"  :icon="Document" circle style="margin-right: 10px;margin-top: 8px;"/>
           </el-tooltip>
           <el-tooltip content="设置" placement="top">
            <el-button type="warning" :disabled="loading" @click="showSetting" :icon="Setting" circle style="margin-right: 10px;margin-top: 8px;"/>
           </el-tooltip>
           <el-tooltip content="测试用例"  placement="top">
              <el-button type="success" :icon="Memo" circle style="margin-right: 40px;margin-top: 8px;" @click="showExample"/>
           </el-tooltip>
          <header-avatar></header-avatar>
        </div>
       
      </el-header>
      <el-container>
        <el-aside width="12%" class="box-aside" id="aside">
          <div class="title">
            <el-icon style="margin:0 5px" :size="20">
              <Calendar />
            </el-icon>
            当前节点
          </div>
          <span class="data">
            {{newDataList[0]}}
          </span>
        </el-aside>
        <el-main style="display:flex;justify-content:center">
          <div id="container" class="canvas-container"></div>
        </el-main>
      </el-container>
    </el-container>


  <!-- 添加节点的对话框 -->
    <el-dialog
    v-model="dialogVisible"
    title="添加节点"
    width="50%"
    @keyup.enter="getNodesData">
  <el-input v-model.trim="addInput" placeholder="请输入数字，批量插入请使用逗号隔开"></el-input>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="getNodesData">
          确认
        </el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 设置抽屉可视化 -->
  <el-drawer
    v-model="settingDrawerVisible"
    title="设置"
    direction="rtl"
    :before-close="handleSettingClose"
  >
      <el-form-item label="节点动画速度">
        <el-slider v-model="v" @change="handleSettingChange"/>
      </el-form-item>
      <el-form-item label="节点大小">
        <el-slider v-model="r" @change="handleSettingChange"/>
      </el-form-item>
      <el-form-item label="节点颜色">
        <el-color-picker v-model="Nodecolor" @change="handleSettingChange" show-alpha />
      </el-form-item>
      <el-form-item>
        <el-button @click="saveSetting" type="primary">保存设置</el-button>
      </el-form-item>
  </el-drawer>

  <!-- 日志展示抽屉 -->
  <el-drawer
    size="50%"
    v-model="logVisible"
    title="日志"
    direction="rtl"
  >
  <div style="display: flex;justify-content: end;margin-bottom: 20px;">
    <el-tooltip content="刷新"  placement="top">
        <el-button @click="refreshLog" type="info" :icon="RefreshLeft">刷新日志</el-button>
    </el-tooltip>
    <el-tooltip content="清空"  placement="top">
        <el-button @click="deleteLog" type="danger" :icon="Delete" >清空日志</el-button>
    </el-tooltip>
  </div>
  <div v-for="item of logList" :key="item.content" style="display: flex; align-items: center;">
    <el-tag type="success" style="margin-right: 20px;">{{ item.createTime }}</el-tag>
    <p style="color: gray;margin-right: 20px;">{{ item.content }}</p>
    <el-tooltip content="查看平衡二叉树"  placement="top">
        <el-button :disabled="loading" @click="showHistoryTree(item.tree)" type="primary" circle :icon="View"></el-button>
    </el-tooltip>
  </div>
  
  </el-drawer>

  <!-- 保存用例输入可视化 -->
  <el-dialog
    v-model="exampleVisable"
    title="保存测试用例"
    width="50%"
    @keyup.enter="saveExample"
    >
  <el-input v-model.trim="saveInput" placeholder="请输入测试用例名称"></el-input>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="exampleVisable = false">取消</el-button>
        <el-button type="primary" @click="saveExample">
          确认
        </el-button>
      </span>
    </template>
  </el-dialog>
  <!-- 测试用例展示抽屉 -->
  <el-drawer
    size="50%"
    v-model="treeVisible"
    title="测试用例管理"
    direction="rtl"
  >
  <div style="display: flex;justify-content: end;margin-bottom: 20px;">
    <el-tooltip content="清空"  placement="top">
        <el-button @click="deleteExample" type="danger" :icon="Delete" >清空测试用例</el-button>
    </el-tooltip>
  </div>
  <div v-for="item of treeList" :key="item.name" style="display: flex; align-items: center;">
    <el-tag size="large" type="success" style="margin-right: 20px;">{{ item.name }}</el-tag>
    <el-tooltip content="查看平衡二叉树"  placement="top">
        <el-button :disabled="loading" @click="showHistoryTree(item.tree)" type="primary" circle :icon="View"></el-button>
    </el-tooltip>
  </div>
  
  </el-drawer>
</template>

<script setup>
import { onMounted,ref,reactive } from "vue";
import HeaderAvatar from '@/components/HeaderAvatar'
import {
  Plus,
  Delete,
  Document,
  Memo,
  Setting,
  View,
RefreshLeft,
Save,
Coin
} from '@element-plus/icons-vue'
import {ElMessage, ElMessageBox, dayjs } from "element-plus";
import * as PIXI from 'pixi.js';
import CircularJson from 'circular-json'
//底部节点距离
const lastInterval=10
const topInterval=30
const settingForm=ref({})
const settingSave=ref(true)
//节点半径
const r=ref(localStorage.getItem("setting")?JSON.parse(localStorage.getItem("setting")).r:35)
//动画速度 v越大速度越小
const v=ref(localStorage.getItem("setting")?JSON.parse(localStorage.getItem("setting")).v:50)
//节点颜色
const Nodecolor=ref(localStorage.getItem("setting")?JSON.parse(localStorage.getItem("setting")).Nodecolor:"lightblue")
// 平衡因子
const LH = 1;
const EH = 0;
const RH = -1;
//添加对话框是否可视化
const dialogVisible=ref(false)
//测试用例输入抽屉是否可视化
const drawerVisible=ref(false)
//设置抽屉可视化
const settingDrawerVisible=ref(false)

// 日志样式可视化
const logVisible=ref(false)

// 保存用例可视化
const exampleVisable=ref(false)
// 测试用例可视化
const treeVisible=ref(false)

//加载效果
const loading=ref(false)
//画布对象
const canvas=ref({})
//新数据添加
const addInput=ref("")
//新数据对象
const newDataList=reactive([1,2,3])
//测试用例名称
const saveInput=ref("")
//目前动画对象
const currentAnimation=[]
const renderTree=ref(null)
// 日志内容
const logList=ref([])
// 测试用例
const treeList=ref([])

//清空树节点
const clearNodes=()=>{
  ElMessageBox.confirm('确定清空节点吗', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    removeChildTree(renderTree.value)
    renderTree.value=null
  }).catch(() => {});
  saveLog("清空树节点")
}

//显示添加对话框
const showDialog=()=>{
  dialogVisible.value=true
}

//画圆并返回圆形节点
const drawCircle=(x,y,r,data,color)=>{
  color=color?color:Nodecolor.value
  const cir=new PIXI.Graphics()
  cir.beginFill(color)
  cir.drawCircle(x,y,r)
  cir.endFill()
  const message=new PIXI.Text(data)
  message.position.set(x,y)
  message.anchor.set(0.5)
  canvas.value.stage.addChild(cir)
  canvas.value.stage.addChild(message)
  return {
    circle:cir,
    content:message
  }
}
//擦除圆
const clearCircle=(node)=>{
  canvas.value.stage.removeChild(node.circle)
  canvas.value.stage.removeChild(node.data)
}
//画线
const drawLine=(x1,y1,x2,y2,color="gray",width=2)=>{
    const line=new PIXI.Graphics();
    line.lineStyle(width, color, 1);
    line.moveTo(x1,y1)
    line.lineTo(x2,y2)
    canvas.value.stage.addChild(line)
    return line
}
let promiseResolve=null;
// 同步锁
const block=()=>{
  return new Promise(res=>promiseResolve=res)
}

//获取树的高度
const getTreeHeight=(node)=>{
  if (node===null)return 0
  if(node.leftChild==null&&node.rightChild==null) return 1;
  return (getTreeHeight(node.leftChild)>getTreeHeight(node.rightChild)?getTreeHeight(node.leftChild):getTreeHeight(node.rightChild))+1
}

//获取树宽
const getTreeWidth=(node)=>{
  return 2**(getTreeHeight(node))*r.value+(2**(getTreeHeight(node))-1)*(lastInterval)
}

//渲染树节点
const renderChildTree=(parent,root,midx,midy,leftx,rightx)=>{
  if(root===null)return
  root.node=drawCircle(midx,midy,r.value,root.data)
  if(parent){
    root.node.line=drawLine(parent.node.content.x,parent.node.content.y,midx,midy)
  }
  renderChildTree(root,root.leftChild,(midx+leftx)/2,midy+topInterval+2*r.value,leftx,midx)
  renderChildTree(root,root.rightChild,(midx+rightx)/2,midy+topInterval+2*r.value,midx,rightx)
}

//清除树节点
const removeChildTree=(root)=>{
  if (root===null)return
  canvas.value.stage.removeChild(root.node.circle)
  canvas.value.stage.removeChild(root.node.content)
  canvas.value.stage.removeChild(root.node.line)
  removeChildTree(root.leftChild)
  removeChildTree(root.rightChild)
}
let n=1
let x1,x2,x3,x4,x5,x6,x7,x8
let y1,y2,y3,y4,y5,y6,y7,y8
// 右旋动画
const rightRotateAnimation=()=>{
  const[root]=currentAnimation
  const {leftChild,rightChild}=root
  if(n>v.value){
    n=1
    promiseResolve("动画结束")
    return
  }
    if(n===1){
      x1=leftChild.node.content.x
      y1=leftChild.node.content.y
      x2=root.node.content.x
      y2=root.node.content.y
      if(rightChild){
        x3=rightChild.node.content.x
        y3=rightChild.node.content.y
      }else{
        x3=root.node.content.x+2*r.value+lastInterval
        y3=root.node.content.y+2*r.value+topInterval
      }
  }
  removeChildTree(root)
  leftChild.node=drawCircle(x1+(x2-x1)*n/v.value,y1+(y2-y1)*n/v.value,r.value,leftChild.data)
  root.node=drawCircle(x2+(x3-x2)*n/v.value,y2+(y3-y2)*n/v.value,r.value,root.data)
  root.node.line=drawLine(x1+(x2-x1)*n/v.value,y1+(y2-y1)*n/v.value,x2+(x3-x2)*n/v.value,y2+(y3-y2)*n/v.value)
  if(leftChild.rightChild){
    const leftRightChild=leftChild.rightChild
    if(n===1){
      x4=leftRightChild.node.content.x
      y4=leftRightChild.node.content.y
      if(rightChild){
        if(rightChild.leftChild){
          const rightleftChild=rightChild.leftChild
          x5=rightleftChild.node.content.x
          y5=rightleftChild.node.content.y
        }else{
          x5=x3-2*r.value-lastInterval
          y5=y3+2*r.value+topInterval
        }
      }else{      
          x5=root.node.content.x
          y5=root.node.content.y+4*r.value+2*topInterval
      }
    }
    renderChildTree(root,leftChild.rightChild,x4+(x5-x4)*n/v.value,y4+(y5-y4)*n/v.value,x4+(x5-x4)*n/v.value-getTreeWidth(leftChild.leftChild)/2,x4+(x5-x4)*n/v.value+getTreeWidth(leftChild.leftChild)/2)
  }
  if(leftChild.leftChild){
    if(n===1){
      x6=leftChild.leftChild.node.content.x
      y6=leftChild.leftChild.node.content.y
    }
    renderChildTree(leftChild,leftChild.leftChild,x6+(x1-x6)*n/v.value,y6+(y1-y6)*n/v.value,x6+(x1-x6)*n/v.value-getTreeWidth(leftChild.leftChild)/2,x6+(x1-x6)*n/v.value+getTreeWidth(leftChild.leftChild)/2)
  }
  if(rightChild){
    if(n===1){
        if(rightChild.rightChild){
        x8=rightChild.rightChild.node.content.x
        y8=rightChild.rightChild.node.content.y
      }else{
        x8=x3+2*r.value+lastInterval
        y8=y3+2*r.value+topInterval
      }
    }
    renderChildTree(root,root.rightChild,x3+(x8-x3)*(n)/v.value,y3+(y8-y3)*(n)/v.value,x3+(x8-x3)*(n)/v.value-getTreeWidth(rightChild)/2,x3+(x8-x3)*(n)/v.value+getTreeWidth(rightChild)/2)
  }
  n++
  requestAnimationFrame(rightRotateAnimation)
}


//右旋
const rightRotate =async (tree) => {
  const line=tree.node.line
  removeChildTree(tree)
  currentAnimation[0]=tree
  rightRotateAnimation()
  await block()
  if(line){
    canvas.value.stage.addChild(line)
    tree.leftChild.node.line=line
  }
  const { leftChild } = tree;
  tree.leftChild = leftChild.rightChild;
  leftChild.rightChild = tree;
  return leftChild;
};

//左旋动画
const leftRotateAnimation=()=>{
  const[root]=currentAnimation
  const {leftChild,rightChild}=root
  if(n>v.value){
    n=1
    promiseResolve("动画结束")
    return
  }
    if(n===1){
      x1=rightChild.node.content.x
      y1=rightChild.node.content.y
      x2=root.node.content.x
      y2=root.node.content.y
      if(leftChild){
        x3=leftChild.node.content.x
        y3=leftChild.node.content.y
      }else{
        x3=root.node.content.x-2*r.value-lastInterval
        y3=root.node.content.y+2*r.value+topInterval
      }
    }
  removeChildTree(root)
  rightChild.node=drawCircle(x1+(x2-x1)*n/v.value,y1+(y2-y1)*n/v.value,r.value,rightChild.data)
  root.node=drawCircle(x2+(x3-x2)*n/v.value,y2+(y3-y2)*n/v.value,r.value,root.data)
  root.node.line=drawLine(x1+(x2-x1)*n/v.value,y1+(y2-y1)*n/v.value,x2+(x3-x2)*n/v.value,y2+(y3-y2)*n/v.value)
  if(rightChild.leftChild){
    const rightleftChild=rightChild.leftChild
    if(n===1){
      x4=rightleftChild.node.content.x
      y4=rightleftChild.node.content.y
      if(leftChild){
        if(leftChild.rightChild){
          const leftRightChild=leftChild.rightChild
          x5=leftRightChild.node.content.x
          y5=leftRightChild.node.content.y
        }else{
          x5=x3+2*r.value+lastInterval
          y5=y3+2*r.value+topInterval
        }
      }else{
          x5=root.node.content.x
          y5=root.node.content.y+4*r.value+2*topInterval
      }
    }
    renderChildTree(root,rightChild.leftChild,x4+(x5-x4)*n/v.value,y4+(y5-y4)*n/v.value,x4+(x5-x4)*n/v.value-getTreeWidth(rightChild.rightChild)/2,x4+(x5-x4)*n/v.value+getTreeWidth(rightChild.rightChild)/2)
  }
  if(rightChild.rightChild){
    if(n===1){
      x6=rightChild.rightChild.node.content.x
      y6=rightChild.rightChild.node.content.y
    }
    renderChildTree(rightChild,rightChild.rightChild,x1+(x6-x1)*(v.value-n)/v.value,y1+(y6-y1)*(v.value-n)/v.value,x1+(x6-x1)*(v.value-n)/v.value-getTreeWidth(rightChild.rightChild)/2,x1+(x6-x1)*(v.value-n)/v.value+getTreeWidth(rightChild.rightChild)/2)
  }
  if(leftChild){
    if(n===1){
        if(leftChild.leftChild){
        x8=leftChild.leftChild.node.content.x
        y8=leftChild.leftChild.node.content.y
      }else{
        x8=x3-2*r.value-lastInterval
        y8=y3+2*r.value+topInterval
      }
    }
    
    renderChildTree(root,root.leftChild,x3+(x8-x3)*(n)/v.value,y3+(y8-y3)*(n)/v.value,x3+(x8-x3)*(n)/v.value-getTreeWidth(leftChild)/2,x3+(x8-x3)*(n)/v.value+getTreeWidth(leftChild)/2)
  }
  n++
  requestAnimationFrame(leftRotateAnimation)
}

//左旋
const leftRotate =async (tree) => {
  const line=tree.node.line
  removeChildTree(tree)
  currentAnimation[0]=tree
  leftRotateAnimation()
  await block()
  if(line){
    canvas.value.stage.addChild(line)
    tree.rightChild.node.line=line
  }
  const { rightChild } = tree;
  tree.rightChild = rightChild.leftChild;
  rightChild.leftChild = tree;
  return rightChild;
};

//左平衡
const leftBalance =async (tree) => {
  const { leftChild } = tree;
  switch (leftChild.bf) {
    case LH:
      leftChild.bf = tree.bf = EH;
      return await rightRotate(tree);
    case RH:
      switch (leftChild.rightChild.bf) {
        case LH:
          tree.bf = RH;
          leftChild.bf = EH;
          break;
        case EH:
          tree.bf = leftChild.bf = EH;
          break;
        case RH:
          tree.bf = EH;
          leftChild.bf = LH;
          break;
      }
      leftChild.rightChild.bf = EH;
      tree.leftChild =await leftRotate(tree.leftChild);
      return await rightRotate(tree);
  }
};

//右平衡
const rightBalance =async (tree) => {
  const { rightChild } = tree;
  switch (rightChild.bf) {
    case RH:
      rightChild.bf = tree.bf = EH;
      return await leftRotate(tree);
    case LH:
      switch (rightChild.leftChild.bf) {
        case RH:
          tree.bf = LH;
          rightChild.bf = EH;
          break;
        case EH:
          tree.bf = rightChild.bf = EH;
          break;
        case LH:
          tree.bf = EH;
          rightChild.bf = RH;
          break;
      }
      rightChild.leftChild.bf = EH;
      tree.rightChild =await rightRotate(tree.rightChild);
      return await leftRotate(tree);
  }
};

//移动动画
let m=1
let text={}
const moveAnimation=()=>{
  if(m>v.value){
    canvas.value.stage.removeChild(text)
    m=1
    text={}
    promiseResolve()
    return
  }
  canvas.value.stage.removeChild(text)
  const [start,end,data]=currentAnimation
  const {x:x1,y:y1}=start.node.content
  const {x:x2,y:y2}=end.node.content
  text=new PIXI.Text(data)
  text.position.set(x1+(x2-x1)*m/v.value,y1+(y2-y1)*m/v.value)
  text.anchor.set(0.5)
  canvas.value.stage.addChild(text)
  m++
  requestAnimationFrame(moveAnimation)
}

//插入节点
let taller = false;
const insertNode =async (tree, data, less, equal) => {
  if (tree == null) {
    taller = true;
    const container=document.querySelector("#container")
    return {
      leftChild:null,
      rightChild:null,
      bf:0,
      data:data,
      node:{
        ...drawCircle(container.offsetWidth/2,topInterval+r.value,r.value,data)
      }
    }
  } else {
    if (equal(data, tree.data)) {
      taller = false;
      return tree;
    } else {
      if (less(data, tree.data)) {
        if(tree.leftChild!==null){
          currentAnimation[0]=tree
          currentAnimation[1]=tree.leftChild
          currentAnimation[2]=data
          requestAnimationFrame(moveAnimation)
          await block()
          tree.leftChild =await insertNode(tree.leftChild, data, less, equal);
        }else{
          taller=true
          const newNode={
            data: data,
            leftChild: null,
            rightChild: null,
            bf: EH,
            node:{
              content:{
                x:tree.node.content.x-2*r.value-lastInterval,
                y:tree.node.content.y+2*r.value+topInterval
              }
            }
          }
          currentAnimation[0]=tree
          currentAnimation[1]=newNode
          currentAnimation[2]=data
          requestAnimationFrame(moveAnimation)
          await block()
          newNode.node=drawCircle(newNode.node.content.x,newNode.node.content.y,r.value,data)
          const{x:x1,y:y1}=tree.node.content
          const{x:x2,y:y2}=newNode.node.content
          newNode.node.line=drawLine(x1,y1,x2,y2)
          tree.leftChild=newNode
        }
        if (taller === true) {
          switch (tree.bf) {
            case LH:
              taller = false;
              return await leftBalance(tree);
            case EH:
              taller = true;
              tree.bf = LH;
              return tree;
            case RH:
              taller = false;
              tree.bf = EH;
              return tree;
          }
        }
      } else {
        if(tree.rightChild!==null){
          currentAnimation[0]=tree
          currentAnimation[1]=tree.rightChild
          currentAnimation[2]=data
          requestAnimationFrame(moveAnimation)
          await block()
          tree.rightChild =await insertNode(tree.rightChild, data, less, equal);
        }else{
          taller=true
          const newNode={
            data: data,
            leftChild: null,
            rightChild: null,
            bf: EH,
            node:{
              content:{
                x:tree.node.content.x+2*r.value+lastInterval,
                y:tree.node.content.y+2*r.value+topInterval
              }
            }
          }
          currentAnimation[0]=tree
          currentAnimation[1]=newNode
          currentAnimation[2]=data
          requestAnimationFrame(moveAnimation)
          await block()
          newNode.node=drawCircle(newNode.node.content.x,newNode.node.content.y,r.value,data)
          const{x:x1,y:y1}=tree.node.content
          const{x:x2,y:y2}=newNode.node.content
          newNode.node.line=drawLine(x1,y1,x2,y2)
          tree.rightChild=newNode
        }
        if (taller === true) {
          switch (tree.bf) {
            case RH:
              taller = false;
              return await rightBalance(tree);
            case EH:
              taller = true;
              tree.bf = RH;
              return tree;
            case LH:
              taller = false;
              tree.bf = EH;
              return tree;
          }
          }
      }
      return tree;
    }
  }
};

//插入新节点
const getNodesData=()=>{
  dialogVisible.value=false
  const list=addInput.value.split(",")
  addInput.value=""
  const res=list.some(item=>{
    return isNaN(+item)
  })
  if(res){
    ElMessage({
      message:"请输入数字，多个数字请用逗号割开",
      type:"warning"
    })
  }else{
    list.forEach(item=>{
      newDataList.push(item)
    })
    loopInsertArr()
  }
}
//递归插入节点
const loopInsertArr=()=>{
  canvas.value.stage.interative=false
  const item=newDataList[0]
  
  insertNode(renderTree.value,+item,(o1,o2)=>{
      return o1<o2
    },(o1,o2)=>{
      return o1==o2
    }).then(res=>{
      loading.value=true
      renderTree.value=res
      reRenderTree()
      newDataList.splice(0,1)
      saveLog(`向平衡二叉树插入${item}`)
      if(newDataList.length!=0){
        loopInsertArr()
      }else{
        loading.value=false
      }
    })
  canvas.value.stage.interative=true
}

// 重新渲染整颗树
const reRenderTree=()=>{
  const container=document.querySelector("#container")
  const midx=container.offsetWidth/2
  removeChildTree(renderTree.value)
  renderChildTree(null,renderTree.value,midx,topInterval,midx-getTreeWidth(renderTree.value)/2,midx+getTreeWidth(renderTree.value))
}

// 清空测试用例
const deleteExample=()=>{
  ElMessageBox.confirm("确定清空测试用例吗","提示",{
    confirmButtonText:"确定",
    cancelButtonText:"取消"
  }).then(()=>{
    treeList.value=[]
    localStorage.removeItem("example")
  }).catch(()=>{
    
  })
  saveLog("清空测试用例")
}

//查看测试用例
const showExample=()=>{
  treeVisible.value=true
  treeList.value=localStorage.getItem("example")?JSON.parse(localStorage.getItem("example")):[]
}

// 保存测试用例
const saveExample=()=>{
  saveLog(`保存测试用例`)
  const treeHistory=localStorage.getItem("example")?JSON.parse(localStorage.getItem("example")):[]
  treeHistory.push({
    tree:renderTree.value,
    name:saveInput.value
  })
  saveInput.value=""
  exampleVisable.value=false
  localStorage.setItem("example",CircularJson.stringify(treeHistory))
}
// 展示历史树
const showHistoryTree=(tree)=>{
  logVisible.value=false
  treeVisible.value=false
  removeChildTree(renderTree.value)
  renderTree.value=tree
  const container=document.querySelector("#container")
  const midx=container.offsetWidth/2
  renderChildTree(null,renderTree.value,midx,topInterval,midx-getTreeWidth(renderTree.value)/2,midx+getTreeWidth(renderTree.value))
  saveLog("查看树节点")
}
// 刷新日志
const refreshLog=()=>{
  logList.value=(localStorage.getItem("log"))?JSON.parse(localStorage.getItem("log")):[]
}
// 清空日志
const deleteLog=()=>{
  ElMessageBox.confirm("确定清空日志吗","提示",{
    confirmButtonText:"确定",
    cancelButtonText:"取消",
    type:"warning"
  }).then(()=>{
    logList.value=[]
    localStorage.removeItem("log")
  }).catch(()=>{

  })
}
//保存日志
const saveLog=(content)=>{
  const logs=localStorage.getItem("log")?JSON.parse(localStorage.getItem("log")):[]
      logs.unshift({
        createTime:dayjs().format("YYYY-MM-DD HH:mm:ss"),
        content:content,
        tree:renderTree.value
      })
      try {
        localStorage.setItem("log",CircularJson.stringify(logs))
      } catch (error) {
        logList.value=[]
        localStorage.removeItem("log")
      }
}
// 展示日志
const showLog=()=>{
  logVisible.value=true
  logList.value=(localStorage.getItem("log"))?JSON.parse(localStorage.getItem("log")):[]
}
//展示设置
const showSetting=()=>{
  settingDrawerVisible.value=true
  settingForm.value={
    v:v.value,
    r:r.value,
    Nodecolor:Nodecolor.value
  }
}
// 处理设置窗口关闭
const handleSettingClose=()=>{
  if(!settingSave.value){
    ElMessageBox.confirm('设置未保存确定退出吗', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          v.value=settingForm.value.v
          r.value=settingForm.value.r
          Nodecolor.value=settingForm.value.Nodecolor
          settingSave.value=true
          reRenderTree()
          settingDrawerVisible.value=false
        }).catch(()=>{
        })
  }else{
    settingDrawerVisible.value=false
  }
}
// 处理保存设置
const saveSetting=()=>{
  settingSave.value=true
  localStorage.setItem("setting",JSON.stringify({
    v:v.value,
    r:r.value,
    Nodecolor:Nodecolor.value
  }))
  ElMessage({
    message:"保存成功",
    type:"success"
  })
  reRenderTree()
}
// 处理设置修改
const handleSettingChange=()=>{
  settingSave.value=false
  reRenderTree()
}

onMounted(() => {
    const container=document.querySelector(`#container`)
    const app = new PIXI.Application({
      backgroundColor: "white",
      resolution:window.devicePixelRatio||1,
      width:container.offsetWidth,
      height:container.offsetHeight
  });
  container.appendChild(app.view)
  canvas.value=app
  const aside=document.querySelector("#aside")
  loopInsertArr()
  addEventListener("resize",()=>{
    removeChildTree(renderTree.value)
    const container=document.querySelector(`#container`)
    container.removeChild(canvas.value.view)
    const app = new PIXI.Application({
      backgroundColor: "white",
      resolution:window.devicePixelRatio||1,
      width:container.offsetWidth,
      height:container.offsetHeight
  });
  container.appendChild(app.view)
  canvas.value=app
    const midx=container.offsetWidth/2
    renderChildTree(null,renderTree.value,midx,topInterval,midx-getTreeWidth(renderTree.value)/2,midx+getTreeWidth(renderTree.value))
  })
});
</script>